<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		高级单例、工厂、构造函数、承诺者
		发布订阅
		
		<script>
			(function(){
				let pond={};//事件池
				
				//向事件池中添加方法
			    const on =function on(tag,fun){
					//先判断事件池里面，有没有tag这个标记属性
					if(!pond.hasOwnProperty(tag)){//没有
						pond[tag]=[];//这个标记属性的值是个空数组
					}
					//去掉重复的
					if(pond[tag].includes(fun)){return}
					pond[tag].push(fun);//通过push追加内容
					console.log(pond);
				}
				//执行事件池中方法
				const fire =function fire(tag,...params){
					let arr=pond[tag]||[];//如果找不到标记属性，默认空数组
					//看一下数组的长度，小于等于0,就是空数组，停止循环
					if(arr.length<=0){return}
					//循环数组，执行函数
					let i,item;
					for(i=0;i<arr.length;i++){
						item=arr[i];
						if(typeof item==="function"){//必须是函数才能执行
							item(...params);//函数传参执行
						}else{//如果不是函数，就给删除
							arr.splice(i,1);//使用 splice 会存在数组 塌陷
							i--;//根据该情况，i--
						}
					}
				}
				//删除事件池中方法
				const off =function off(tag,fun){
					let arr=pond[tag]||[];//如果找不到标记属性，默认空数组
					//看一下数组的长度，小于等于0,就是空数组，停止循环
					if(arr.length<=0){return}
					//循环数组，item刚好等传递过来的函数
					let i,item;
					for(i=0;i<arr.length;i++){
						item=arr[i];
						if(item==fun){//删除
							//arr.splice(i,1);
							arr[i]=null;//也可解决数组塌陷
							return;
						}
					}
				}
				
				let sub={
					on,
					fire,
					off
				}
				
				if(typeof window!==undefined){//浏览器
					window.sub=sub;
				}
				
				//nodejs webpack
				if(typeof module==="object"&&typeof module.exports==="object"){
					module.exports=sub;
				}
			})()
			
			function funca(){
				console.log("111");
			}
			function funcb(){
				console.log("222");
				sub.off("A",funca);
				sub.off("A",funcb);
			}
			function funcc(){
				console.log("333");
			}
			function funcd(){
				console.log("444");
			}
			function funce(){
				console.log("555");
			}

			sub.on("A",funca);
			sub.on("A",funcb);
			sub.on("A",funcc);
			sub.on("A",funcd);
			sub.on("A",funce);
			
			setInterval(()=>{
				sub.fire("A");
			},1000)
			
			
			
			
			
			
			
			// function funca(n,m){
			// 	console.log("111",n,m);
			// }
			// sub.on("A",funca);//向事件池中添加方法
			
			// function funcaa(n,m){
			// 	console.log("222",n,m);
			// }
			// function funcaaa(n,m){
			// 	console.log("333",n,m);
			// }
			// sub.on("A",funcaa);//向事件池中添加方法
			// sub.on("A",funcaa);//向事件池中添加方法
			// sub.on("A",funcaa);//向事件池中添加方法
			// sub.on("A","hahaha");//向事件池中添加方法
			// sub.on("A",funcaaa);//向事件池中添加方法
			
			// // sub.fire("A",10,20);//执行事件池中的方法
			// // sub.fire("B",10,20);
			
			// sub.off("A",funcaa);//删除事件池中的方法
		</script>
	</body>
</html>
